home *** CD-ROM | disk | FTP | other *** search
/ Adobe Graphics & Publishing SDK 1996 December / Adobe Graphics & Publishing SDK 1996 December.iso / mac / After Effects 3.1 SDK Mac / Examples / I⁄O Samples / Filmstrip FXIF / FILM_Write.c < prev    next >
Text File  |  1996-06-04  |  9KB  |  406 lines

  1. /**
  2.     FILM_Write.c
  3.     
  4.     Part of the Adobe After Effects 3.1 SDK    
  5.     Copyright (c)1993-96, Adobe Systems Inc, All Rights Reserved.
  6.  
  7.     Revision History
  8.         1.0, created by dmw
  9. **/
  10.  
  11. #include "PIFormatT.h"
  12. #include "Film.h"
  13. #include <string.h>
  14.  
  15.  
  16. //╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  17. // Convert a frame count into a timecode
  18.  
  19. #define    DropFramesPerTenMin        17982
  20. #define    DropFramesPerMin        1798
  21.  
  22. enum {
  23.     ffFrameCount =     1,                    // count in frames        FFFFF
  24.     ffNonDrop24 =     24,                    // 24fps                HH:MM:SS:FF
  25.     ffNonDrop25 =     25,                    // 25fps                HH:MM:SS:FF
  26.     ffNonDrop30 =     30,                    // 30fps, non-drop        HH:MM:SS:FF
  27.     ffNonDrop100 =     100,                // 100fps                HH:MM:SS:FFF
  28.     ffNonDrop600 =     600,                // 600fps                HH:MM:SS:FFF
  29.     ffDropFrame =     29,                    // 30fps, drop-frame    HH;MM;SS;FF
  30.     ffFeetFrame16 = 16,                    // Feet.Frames    (35mm)    ffff.FF
  31.     ffFeetFrame40 = 40,                    // Feet.Frames    (16mm)    ffff.FF
  32.     
  33.     ffType =        0x03FF,                // mask for types
  34.     
  35.     ffDelta =        0x4000,                // delta symbol in front of time
  36.     ffTensHours =    0x3000,                // show tens of hours
  37.     ffTensFlag =    0x2000,                // test bit for tens of hours
  38.     ffHours =        0x1000,                // show hours
  39.     ffOffset =        0x0800                // +SS:FF or -SS:FF
  40. };
  41.  
  42.  
  43. //╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  44. // append two pascal strings
  45.  
  46. static void Append (StringPtr str1, StringPtr str2)
  47. {
  48.     BlockMove(str2+1,str1+1+str1[0],str2[0]);
  49.     str1[0] += str2[0];
  50. }
  51.  
  52.  
  53. //╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤╤
  54. // Do a numeric conversion to H:MM:SS:FFF
  55.  
  56. static void LocalConvert (long time, short fps, short flags, char sep, StringPtr number)
  57. {
  58.     short i = 1, hours, mins, secs, frames;
  59.     
  60.     if (time < 0) {
  61.         number[i++] = '-';
  62.         time = -time;
  63.     }
  64.     
  65.     frames = time % fps;
  66.     secs = (time / fps) % 60;
  67.     mins = (time / (fps * 60)) % 60;
  68.     hours = (time / (fps * 60 * 60)) % 60;
  69.     
  70.     if (!(flags & ffOffset)) {
  71.         if (flags & ffTensFlag) {
  72.             number[i++] = '0' + ((hours / 10) % 10);
  73.         }
  74.         if (flags & ffHours) {
  75.             number[i++] = '0' + (hours % 10);
  76.             number[i++] = sep;
  77.         }
  78.         number[i++] = '0' + ((mins / 10) % 10);
  79.         number[i++] = '0' + (mins % 10);
  80.         number[i++] = sep;
  81.     }
  82.     number[i++] = '0' + ((secs / 10) % 10);
  83.     number[i++] = '0' + (secs % 10);
  84.     number[i++] = sep;
  85.     if (fps <= 100) {
  86.         number[i++] = '0' + ((frames / 10) % 10);
  87.         number[i++] = '0' + (frames % 10);
  88.     }
  89.     else {
  90.         number[i++] = '0' + ((frames / 100) % 10);
  91.         number[i++] = '0' + ((frames / 10) % 10);
  92.         number[i++] = '0' + (frames % 10);
  93.     }
  94.     number[0] = i-1;
  95. }
  96.  
  97.  
  98. static void TimecodeToStr (long frames, short format, StringPtr str)
  99. {
  100.     Str63                temp;
  101.     short                fps, remain;
  102.     long                offset;
  103.     
  104.     switch (format & ffType) {
  105.         case ffFeetFrame16:
  106.         case ffFeetFrame40:
  107.             str[0] = 0;
  108.  
  109.             switch (format & ffType) {
  110.                 case ffFeetFrame16:    fps = 16;    break;
  111.                 case ffFeetFrame40:    fps = 40;    break;
  112.             }
  113.             
  114.             if (frames < 0) {
  115.                 Append(str, (StringPtr)"\p-");
  116.                 frames = -frames;
  117.             }
  118.  
  119.             NumToString(frames / fps, temp);
  120.             Append(str, temp);
  121.             NumToString(remain = frames % fps, temp);
  122.             
  123.             Append(str, (StringPtr)"\p+");
  124.             
  125.             if (remain < 10) Append(str, (StringPtr)"\p0");
  126.             Append(str, temp);
  127.             break;
  128.         case ffNonDrop24:
  129.         case ffNonDrop25:
  130.         case ffNonDrop30:
  131.         case ffNonDrop100:
  132.         case ffNonDrop600:
  133.             switch (format & ffType) {
  134.                 case ffNonDrop24:    fps = 24;    break;
  135.                 case ffNonDrop25:    fps = 25;    break;
  136.                 case ffNonDrop30:    fps = 30;    break;
  137.                 case ffNonDrop100:    fps = 100;    break;
  138.                 case ffNonDrop600:    fps = 600;    break;
  139.             }
  140.             LocalConvert(frames, fps, format, ':', str);
  141.             break;
  142.         case ffDropFrame:
  143.             offset = (frames / DropFramesPerTenMin) * 18;    // 18 frames per 10 minutes
  144.             remain = frames % DropFramesPerTenMin;            // how much left over?
  145.             if (remain >= 1800) {                            // first minute is special
  146.                 offset += 2;
  147.                 remain -= 1800;
  148.             }
  149.             else remain = 0;
  150.             
  151.             offset += (remain / DropFramesPerMin) * 2;        // 2 frames per minute
  152.             LocalConvert(frames + offset, 30, format, ';', str);
  153.             break;
  154.         case ffFrameCount:
  155.             str[0] = 0;
  156.             NumToString(frames, temp);
  157.             Append(str, temp);
  158.             break;
  159.         default:
  160.             Append(str, (StringPtr)"\p----");
  161.             break;
  162.     }
  163. }
  164.  
  165.  
  166. static OSErr DrawLeading (FormatRecordTPtr fpt)
  167. {
  168.     OSErr            err = 0;
  169.     long            rowbytes;
  170.     GWorldPtr        destworld;
  171.     GWorldPtr        oldworld;
  172.     GDHandle        olddev;
  173.     Ptr                base;
  174.     SInt8            mode;
  175.     myRevertInfo**    ri;
  176.     RGBColor        thecolor;
  177.     Rect            padrect;
  178.     Str31            str;
  179.     Str27            temp;
  180.     long            i;
  181.     char             *src;
  182.     char             *dst = fpt->data;
  183.     long            *dst_l;
  184.     long            j;
  185.     char            a;
  186.     
  187.     ri = (myRevertInfo**)fpt->revertInfo;
  188.     destworld = DH(ri)->number_wld;
  189.  
  190.     padrect.top = padrect.left = 0;
  191.     padrect.right = fpt->imageSize.h;
  192.     padrect.bottom = FILM_LEAD;
  193.  
  194.     mode = true32b;
  195.     SwapMMUMode(&mode);
  196.     
  197.     if (LockPixels(destworld->portPixMap)) {
  198.         base = GetPixBaseAddr(destworld->portPixMap);
  199.         rowbytes = (*destworld->portPixMap)->rowBytes & 0x3FFF;
  200.         
  201.         GetGWorld(&oldworld,&olddev);
  202.         SetGWorld(destworld,nil);
  203.     
  204. //        TextFont(geneva);
  205.         TextSize(9);
  206.         thecolor.red = thecolor.green = thecolor.blue = 0xBFFF;
  207.         RGBForeColor(&thecolor);
  208.         PaintRect(&padrect);
  209.         thecolor.red = 0xFFFF;
  210.         thecolor.green = 0xFFFF;
  211.         thecolor.blue = 0;
  212.         RGBForeColor(&thecolor);
  213.         MoveTo(padrect.left,padrect.top);
  214.         Line(0,0);
  215.         thecolor.red = thecolor.green = thecolor.blue = 0;
  216.         RGBForeColor(&thecolor);
  217.         TimecodeToStr(DH(ri)->film_rec.numFrames, DH(ri)->film_rec.framesPerSec, str);
  218.         MoveTo(padrect.left+4,padrect.bottom-5);
  219.         DrawString(str);
  220.         NumToString(DH(ri)->film_rec.numFrames,temp);
  221.         for (i=0; i<5-temp[0]; i++) str[i+1] = '0';
  222.         str[0] = 5-temp[0];
  223.         Append(str,temp);
  224.         MoveTo(padrect.right-4-StringWidth(str),padrect.bottom-5);
  225.         DrawString(str);
  226.     
  227.     
  228.         // now destworld has the frame #/timecode in it --> copy it into fpt->data
  229.         src = base;
  230.         for (i=0; i<FILM_LEAD; i++) {
  231.             BlockMove(src, dst, sizeof(long) * padrect.right);
  232.  
  233.             dst_l = (long*)dst;
  234.             for (j=0; j<padrect.right; j++) {
  235.                 a = *(char*)dst_l;
  236.                 *dst_l = (*dst_l) << 8;
  237.                 ((char*)dst_l)[3] = a;
  238.                 dst_l++;
  239.             }
  240.             
  241.             dst += sizeof(long) * padrect.right;
  242.             src += rowbytes;
  243.             
  244.         }
  245.         
  246.         UnlockPixels(destworld->portPixMap);
  247.     }
  248.     
  249.     SetGWorld(oldworld,olddev);
  250.     SwapMMUMode(&mode);
  251.  
  252.     return err;
  253. }
  254.  
  255. void WritePrepare (Ptr Stuff, long *data, short *result)
  256. {
  257.     FormatRecordPtr    fp = (FormatRecordPtr)Stuff;
  258.     fp -> maxData /= 2;
  259.     
  260.     *result = 0;
  261.     
  262. }
  263.  
  264.  
  265.  
  266. void WriteStart (Ptr Stuff, long *data, short *result)
  267. {
  268.     OSErr                err = 0;
  269.     myRevertInfo        **ri;
  270.     FormatRecordTPtr    fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
  271.     TimeInfoHandle        ti;
  272.     Handle                dataH;
  273.  
  274.     ri = (myRevertInfo**)fpt->revertInfo;
  275.     ti = fpt->time_ext.time_info;
  276.  
  277.     if (ri) { 
  278.         long rowsat;
  279.         
  280.         rowsat = fpt->maxData / (4L * (long)fpt->imageSize.h);
  281.     
  282.         if (rowsat < FILM_LEAD) rowsat = FILM_LEAD;
  283.         else if (rowsat > fpt->imageSize.v) rowsat = fpt->imageSize.v;
  284.  
  285.         DH(ri)->rowsat = rowsat;
  286.         DH(ri)->film_rec.framesPerSec = (DH(ti)->write_fixed_fps) >> 16;
  287.         DH(ri)->dataH = NULL;
  288.         dataH = NewHandle(rowsat * (long)fpt->imageSize.h  * 4L);
  289.         
  290.         if (dataH) {
  291.             HLock(dataH);
  292.             DH(ri)->dataH = dataH;
  293.             
  294.             fpt->data =  DH(dataH);
  295.             
  296.             fpt->theRect.left = 0;
  297.             fpt->theRect.right = fpt->imageSize.h;
  298.             fpt->theRect.top = 0;
  299.             fpt->theRect.bottom = rowsat;
  300.             fpt->loPlane = 0;
  301.             fpt->hiPlane = 3;
  302.             fpt->colBytes = 4;
  303.             fpt->rowBytes = 4 * (long)fpt->imageSize.h;
  304.             fpt->planeBytes = 1;
  305.             
  306.         } else {
  307.             err = memFullErr;
  308.         }
  309.         
  310.     } else {
  311.         err = formatBadParameters;
  312.     }
  313.     
  314.     *result = err;
  315. }
  316.  
  317.  
  318. void WriteContinue (Ptr Stuff, long *data, short *result)
  319. {
  320.     OSErr                err = 0;
  321.     myRevertInfo        **ri;
  322.     FormatRecordTPtr    fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
  323.     TimeInfoHandle        ti;
  324.     long                bytes_written;
  325.     long                rows;
  326.     Boolean                done = FALSE;
  327.     
  328.     ri = (myRevertInfo**)fpt->revertInfo;
  329.     ti = fpt->time_ext.time_info;
  330.     
  331.     if (fpt->advanceState == NULL) {
  332.         err = errPlugInHostInsufficient;
  333.     }
  334.     
  335.     if (!err) {
  336.         err = SetFPos(fpt->dataFork, fsFromLEOF, 0);
  337.     }
  338.     
  339.     if (!err) {
  340.         if (ri && fpt->data) {
  341.             
  342.             do {
  343.                 rows = fpt->theRect.bottom - fpt->theRect.top;
  344.                 
  345.                 bytes_written = fpt->imageSize.h * rows * 4L;
  346.                 
  347.                 err = FSWrite(fpt->dataFork, &bytes_written, fpt->data);
  348.                 if (err) break;
  349.                 
  350.  
  351.                 fpt->theRect.top = fpt->theRect.bottom;
  352.                 fpt->theRect.bottom = fpt->theRect.top + DH(ri)->rowsat;
  353.                 
  354.                 if (fpt->theRect.bottom > fpt->imageSize.v) 
  355.                     fpt->theRect.bottom = fpt->imageSize.v;
  356.                 
  357.                 if (fpt->theRect.top >= fpt->imageSize.v) done = TRUE;
  358.                 
  359.                 if (!done) fpt->advanceState();
  360.                 
  361.             } while (!done);
  362.                         
  363.             if (!err) {
  364.                 bytes_written = fpt->imageSize.h * FILM_LEAD * 4;
  365.                 err = DrawLeading(fpt);
  366.                 if (!err) {
  367.                     err = FSWrite(fpt->dataFork, &bytes_written, fpt->data);
  368.                 }
  369.             }
  370.             
  371.             fpt->data = NULL;
  372.             DisposeHandle(DH(ri)->dataH);
  373.             DH(ri)->dataH = NULL;
  374.             DH(ri)->film_rec.numFrames++;
  375.             
  376.         } else {
  377.             err = formatBadParameters;
  378.         }
  379.         
  380.     }
  381.     
  382.     *result = err;
  383.     
  384. }
  385.  
  386.  
  387. void WriteFinish (Ptr Stuff, long *data, short *result)
  388. {
  389.     myRevertInfo        **ri;
  390.     FormatRecordTPtr    fpt = (FormatRecordTPtr)(Stuff - sizeof(TimeExtension));
  391.     TimeInfoHandle        ti;
  392.  
  393.     ri = (myRevertInfo**)fpt->revertInfo;
  394.     ti = fpt->time_ext.time_info;
  395.  
  396.     *result = 0;
  397.  
  398.     if (ri) { 
  399.         DisposeHandle(DH(ri)->dataH);
  400.         DH(ri)->dataH = NULL;
  401.         fpt->data = NULL;
  402.     } else {
  403.         *result = formatBadParameters;
  404.     }
  405. }
  406.